interface ParameterParser {
    parseParam(parameterString: string): any[];
}

interface CsrParam {
    patternName: string;
    paramName: string;
}
interface CsrParamPattern {
    id: number;
    patternName: string;
    pattern: RegExp;
    groupIndex: number; //捕获组的索引
    description?: string;
}


/**
 * 用于初始的解析csr表达式的参数列表
 * 对外提供parseParam接口
 */
class CSRParameterParser implements ParameterParser {
    // 参数列表正则匹配
    private static readonly PARAM_REGEX_CONFIG: Readonly<CsrParamPattern[]> = [
        // 匹配  <=/ 同步形式的
        {
            id: 0,
            patternName: "同步",
            pattern: /<=\/(.+)$/,
            groupIndex: 1,
            description: "同步属性"
        },
        {
            id: 1,
            patternName: "引用",
            pattern: /\${([^}]+)\}/,
            groupIndex: 1,
            description: "引用属性"

        }
    ] as const;


    /**
     * 
     * @param str 输入的单个参数带匹配 "<=/StatusScanner_1.Status"
     * @returns 提取的参数名称和类型，例如  {paramName: "StatusScanner_1.Status", patternName:"同步属性"}
     */
    private static parseSingleParam(str: string): CsrParam | any {
        if (!str || typeof str !== 'string') {
            return null;
        }
        console.log(`str is ${str}`)


        for (const curPattern of CSRParameterParser.PARAM_REGEX_CONFIG) {
            console.log(`curPattern.pattern is ${curPattern.pattern}`)
            const match = str.match(curPattern.pattern);
            console.log(`curPattern.patternName is ${curPattern.patternName}`)
            console.log(`match[0] is ${match?match[0]:'无匹配'}`)
            if (match && match[curPattern.groupIndex]) {
                console.log(`curPattern.patternName is ${curPattern.patternName}`)
                console.log(`match[curPattern.groupIndex] is ${match[curPattern.groupIndex]}`)
                return {
                    paramName: match[curPattern.groupIndex],
                    patternName: curPattern.patternName,
                }
            }
        }
        return null;
    }

    /**
     * 
     * @param parameterString 输入代表参数列表字符串，即第一个 "|>"之前的字符串
     * @returns 参数列表数组，每一项都包含了参数名称和参数的类型（同步，引用...）
     */
    parseParam(parameterString: string): CsrParam[] {
        console.log(`parameterString is ${parameterString}`);

        if (!parameterString || parameterString.trim().length === 0) {
            return [];
        }
        const paramArray = parameterString.split(';').map(item => item.trim());
        const res: CsrParam[] = [];

        paramArray.map((curstr: string) => {
            console.log(`curstr is ${curstr}`);

            const curParam = CSRParameterParser.parseSingleParam(curstr);
            if (curParam !== null) {
                res.push(curParam);
            }
        })

        return res;
    }
}


interface singleStepParse {
    parseSingleStep2Fun(exprString: string): (...args: any[]) => any;
}

/**
 * 表达式单步解析  对外提供parseSingleStep2Fun接口
 * 用于将expr()或string.xxx转换为函数
 */
class CSRFuncSingleStepParser implements singleStepParse {

    /**
     * 统一的表达式/字符串函数解析接口
     * @param exprString 表达式或字符串函数，如 expr(($1 + 16 !=0)&&($2 != 65536)) 或 string.format("Hello %s", $1)
     * @returns 匿名函数，调用时传入参数计算表达式
     */
    parseSingleStep2Fun(exprString: string): (...args: any[]) => any {
        try {
            const trimmedExpr = exprString.trim();

            // 根据前缀决定调用哪个解析函数
            if (trimmedExpr.startsWith("expr(") || trimmedExpr.startsWith("(")) {
                // 表达式类型，调用 parseExpr
                return CSRFuncSingleStepParser.parseExpr(exprString);
            } else if (trimmedExpr.startsWith("string.") || trimmedExpr.startsWith("stringfun(")) {
                // 字符串函数类型，调用 parseStringFun
                return CSRFuncSingleStepParser.parseStringFun(exprString);
            } else {
                // 无法识别的类型，尝试作为表达式处理
                console.warn(`无法识别的表达式类型，将尝试作为表达式处理: ${exprString}`);
                return CSRFuncSingleStepParser.parseExpr(exprString);
            }
        } catch (error) {
            throw new Error(`统一解析错误`);
        }
    }
    /**
     * @param exprString 表达式字符串
     * @returns 判断表达式里是否有参数 $1...
     */
    private static hasParam(exprString: string): boolean {
        return /\$\d+/.test(exprString);
    }

    // string类型函数处理
    private static readonly STRING = {
        format: (str: string, ...args: any[]) => {
            let result = '';
            let argIndex = 0;

            for (let i = 0; i < str.length; i++) {
                if (str[i] === '%' && i + 1 < str.length) {
                    const specifier = str[i + 1];

                    if (specifier === '%') {
                        // 处理 %% 转义（输出一个 %）
                        result += '%';
                        i++; // 跳过下一个 %
                    } else if (specifier === 's' || specifier === 'd') {
                        // 处理 %s 和 %d
                        if (argIndex < args.length) {
                            const arg = args[argIndex++];

                            if (specifier === 's') {
                                // %s - 字符串
                                result += String(arg);
                            } else if (specifier === 'd') {
                                // %d - 整数
                                result += Math.trunc(Number(arg)).toString();
                            }

                            i++; // 跳过格式说明符
                        } else {
                            // 参数不足，保持原格式
                            result += str[i];
                        }
                    } else {
                        // 不支持的格式说明符，保持原样
                        result += str[i];
                    }
                } else {
                    result += str[i];
                }
            }

            return result;
        },

        sub: (s: string, start: number, end: number) => s.substring(start - 1, end),
        gsub: (s: string, pattern: string, replacement: string) => {
            return s.split(pattern).join(replacement);
        },
        upper: (s: string) => s.toUpperCase(),
        lower: (s: string) => s.toLowerCase(),
        cmp: (a: string, b: string) => a === b
    };



    /**
     * 解析字符串函数的参数列表
     * @param argsStr 参数字符串，如 '"xxx", $1, "aaa"'
     * @returns 解析后的参数数组
     */
    private static parseStringArgs(argsStr: string): any[] {
        if (!argsStr.trim()) return [];

        const args: any[] = [];
        let current = '';
        let inQuotes = false;
        let quoteChar = '';
        let escapeNext = false;

        for (let i = 0; i < argsStr.length; i++) {
            const char = argsStr[i];

            if (escapeNext) {
                current += char;
                escapeNext = false;
                continue;
            }

            if (char === '\\') {
                escapeNext = true;
                current += char;
                continue;
            }

            if ((char === '"' || char === "'") && !inQuotes) {
                inQuotes = true;
                quoteChar = char;
                current += char;
            } else if (char === quoteChar && inQuotes) {
                inQuotes = false;
                current += char;
                // 结束字符串，添加到参数列表
                args.push(current);
                current = '';
                // 跳过可能的逗号和空格
                while (i + 1 < argsStr.length && (argsStr[i + 1] === ',' || argsStr[i + 1] === ' ')) {
                    i++;
                }
            } else if (char === ',' && !inQuotes) {
                // 参数分隔符
                if (current.trim()) {
                    const trimmed = current.trim();
                    // 处理占位符或数字
                    if (trimmed.startsWith('$')) {
                        args.push(trimmed);
                    } else if (!isNaN(Number(trimmed))) {
                        args.push(Number(trimmed));
                    } else {
                        args.push(trimmed);
                    }
                }
                current = '';
            } else {
                current += char;
            }
        }

        // 处理最后一个参数
        if (current.trim()) {
            const trimmed = current.trim();
            if (trimmed.startsWith('$')) {
                args.push(trimmed);
            } else if (!isNaN(Number(trimmed))) {
                args.push(Number(trimmed));
            } else {
                // 处理未加引号的字符串（简单情况）
                args.push(trimmed);
            }
        }

        return args;
    }


    /**
     * 
     * @param exprString 字符串expr(($1 & 16 != 0) && ($2 != 65536))
     * @returns 匿名函数 fun(param1, param2) 调用该函数传值
     */
    private static parseExpr(exprString: string): (...args: any[]) => any {
        try {
            let processExpr = exprString.trim();
            if (processExpr.startsWith("expr(") && processExpr.endsWith(")")) {
                processExpr = processExpr.substring(5, processExpr.length - 1);
            }

            if (!CSRFuncSingleStepParser.hasParam(exprString)) {
                return () => {
                    new Function(`return ${processExpr};`)();
                }
            }

            return (...args: any[]) => {
                try {
                    for (let i = 0; i < args.length; i++) {
                        const param = `\\$${i + 1}`;
                        const regex = new RegExp(param, 'g');
                        processExpr = processExpr.replace(regex, `args[${i}]`)
                    }
                    return new Function('args', `return ${processExpr};`)(args);
                } catch (error) {
                    throw new Error(`表达式构造错误`);
                }
            };
        } catch (error) {
            throw new Error(`表达式解析错误`)
        }
    }



    /**
     * 解析字符串函数表达式
     * @param exprString 字符串函数表达式，如 string.format("Hello %s", $1) 或 string.cmp($1, "test")
     * @returns 匿名函数，调用时传入参数计算表达式
     */
    private static parseStringFun(exprString: string): (...args: any[]) => any {
        try {
            let processExpr = exprString.trim();

            // 检查是否有参数占位符
            if (!CSRFuncSingleStepParser.hasParam(processExpr)) {
                // 没有参数，直接返回计算结果
                return () => {
                    try {
                        // 提取函数名和参数
                        const match = processExpr.match(/^string\.(\w+)\(([^)]*)\)$/);
                        if (!match) {
                            throw new Error(`无效的字符串函数表达式: ${processExpr}`);
                        }

                        const funcName = match[1];
                        const argsStr = match[2];
                        const args = CSRFuncSingleStepParser.parseStringArgs(argsStr);

                        return CSRFuncSingleStepParser.generateStringFunction(funcName, args);
                    } catch (error) {
                        throw new Error(`字符串函数执行错误`);
                    }
                };
            }

            // 有参数，返回需要传入参数的函数
            return (...args: any[]) => {
                try {
                    let processedExpr = processExpr;

                    // 替换参数占位符
                    for (let i = 0; i < args.length; i++) {
                        const param = `\\$${i + 1}`;
                        const regex = new RegExp(param, 'g');
                        processedExpr = processedExpr.replace(regex, `args[${i}]`);
                    }

                    // 提取函数名和参数部分
                    const match = processedExpr.match(/^string\.(\w+)\(([^)]*)\)$/);
                    if (!match) {
                        throw new Error(`无效的字符串函数表达式: ${processedExpr}`);
                    }

                    const funcName = match[1];
                    const argsStr = match[2];

                    // 解析参数（此时参数中可能包含 args[0], args[1] 等）
                    const finalArgs = CSRFuncSingleStepParser.parseDynamicArgs(argsStr, args);

                    return CSRFuncSingleStepParser.generateStringFunction(funcName, finalArgs);
                } catch (error) {
                    throw new Error(`字符串函数计算错误`);
                }
            };
        } catch (error) {
            throw new Error(`字符串函数解析错误`);
        }
    }


    /**
     * 解析动态参数（可能包含 args[0], args[1] 等）
     */
    private static parseDynamicArgs(argsStr: string, externalArgs: any[]): any[] {
        if (!argsStr.trim()) return [];

        try {
            const argParts = CSRFuncSingleStepParser.splitArgs(argsStr);
            const finalArgs: any[] = [];

            for (const argPart of argParts) {
                if (argPart.trim().startsWith('args[') && argPart.includes(']')) {
                    // 包含 args[n] 的表达式，需要动态计算
                    const computedValue = new Function('args', `return ${argPart}`)(externalArgs);
                    finalArgs.push(computedValue);
                } else if ((argPart.startsWith('"') && argPart.endsWith('"')) ||
                    (argPart.startsWith("'") && argPart.endsWith("'"))) {
                    // 字符串字面量
                    finalArgs.push(argPart.substring(1, argPart.length - 1));
                } else if (!isNaN(Number(argPart)) && argPart.trim() !== '') {
                    // 数字
                    finalArgs.push(Number(argPart));
                } else {
                    // 其他情况，直接作为字符串
                    finalArgs.push(argPart);
                }
            }

            return finalArgs;
        } catch (error) {
            throw new Error(`参数解析错误`);
        }
    }

    /**
     * 分割参数字符串，处理字符串内的逗号
     */
    private static splitArgs(argsStr: string): string[] {
        const args: string[] = [];
        let current = '';
        let inQuotes = false;
        let quoteChar = '';
        let escapeNext = false;

        for (let i = 0; i < argsStr.length; i++) {
            const char = argsStr[i];

            if (escapeNext) {
                current += char;
                escapeNext = false;
                continue;
            }

            if (char === '\\') {
                escapeNext = true;
                current += char;
                continue;
            }

            if ((char === '"' || char === "'") && !inQuotes) {
                inQuotes = true;
                quoteChar = char;
                current += char;
            } else if (char === quoteChar && inQuotes) {
                inQuotes = false;
                current += char;
            } else if (char === ',' && !inQuotes) {
                args.push(current.trim());
                current = '';
            } else {
                current += char;
            }
        }

        if (current.trim()) {
            args.push(current.trim());
        }

        return args;
    }


    /**
     * 执行字符串函数
     * @param funcName 函数名
     * @param args 参数数组
     * @returns 函数执行结果
     */
    private static generateStringFunction(funcName: string, args: any[]): any {
        const stringFunc = (CSRFuncSingleStepParser.STRING as any)[funcName];
        if (!stringFunc) {
            throw new Error(`不支持的字符串函数: ${funcName}`);
        }
        return stringFunc(...args);
    }

}

interface calcuteExpression {
    calculate(completeStr: string): string | number;
}

interface stepInfo {
    stepFunction: (...args: any[]) => any;
    stepParams: any;
}

export class CSRCalculator implements calcuteExpression {
    private initParams: CsrParam[];
    private steps: stepInfo[];

    constructor(fullCsrExpression: string) {
        console.log(`fullCsrExpression is : ${fullCsrExpression} `)
        const stepsStringArray = fullCsrExpression.split(/\s*\|>\s*/);

        if (stepsStringArray.length < 2) {
            console.log("表达式无效，步骤不足，请检查输入")
            throw new Error("表达式无效，步骤不足，请检查输入")
        }

        // 解析参数部分
        const initParamString: string = stepsStringArray[0];
        console.log(`initParamString is ${initParamString}`)
        this.initParams = new CSRParameterParser().parseParam(initParamString);

        // 解析剩余表达式部分
        this.steps = stepsStringArray.slice(1).map(stepExpr => {
            return {
                stepFunction: new CSRFuncSingleStepParser().parseSingleStep2Fun(stepExpr),
                stepParams: stepExpr
            }
        })

    }

    calculate(...params: any[]): string | number {
        if (params.length !== this.initParams.length) {
            throw new Error(`参数数量不匹配，期望${this.initParams.length}， 实际得到${params.length}个参数`);
        }

        let curResult: string | number = 0;
        for (let i = 0; i < this.steps.length; i++) {
            const curStep = this.steps[i];

            if (i === 0) {
                curResult = curStep.stepFunction(...params)
            } else {
                // 后续步骤只使用前一步的参数作为表达式 $1
                curResult = curStep.stepFunction(curResult);
            }
        }
        return curResult;
    }

    public printAllInitParams(): void {
        console.log("参数列表");
        for(let i = 0; i < this.initParams.length; i++) {
            console.log(`参数类型：${this.initParams[i].patternName}, 参数名称：${this.initParams[i].paramName}`);
        }

    }
}


